package com.husky.easyexcle.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.husky.easyexcle.entity.ReadExcelExtraEntity;
import com.husky.easyexcle.entity.ReadExcelIndexOrNameEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.Assert;

import java.util.List;
import java.util.function.Consumer;

/**
 * @Author husky
 * @Date 2023/2/21 11:01
 * @Description: 额外信息（批注、超链接、合并单元格信息）监听器
 **/
@Slf4j
public class ReadExcelExtraListener implements ReadListener<ReadExcelExtraEntity> {

    /**
     * 每隔51条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 51;

    /**
     * 没有返回的值的函数式接口
     */
    private final Consumer<List<ReadExcelExtraEntity>> consumer;

    public ReadExcelExtraListener(Consumer<List<ReadExcelExtraEntity>> consumer){

        this.consumer = consumer;
    }

    /**
     * 缓存的数据
     */
    private List<ReadExcelExtraEntity> dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 这个每一条数据解析都会来调用
     * @param readExcelExtraEntity 额外信息（批注、超链接、合并单元格信息） 读取 Excel 对应实体类
     * @param analysisContext 获取Excel上下文对象
     */
    @Override
    public void invoke(ReadExcelExtraEntity readExcelExtraEntity, AnalysisContext analysisContext) {
        // 放入结果集
        dataList.add(readExcelExtraEntity);

        //  不超过咱们期望的数据集大小
        if(dataList.size() >= BATCH_COUNT){
            consumer.accept(dataList);
            dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 返回额外信息（批注、超链接、合并单元格信息读取）时调用
     * @param cellExtra 单元格 额外信息（批注、超链接、合并单元格信息）
     * @param analysisContext 获取Excel上下文对象
     */
    @Override
    public void extra(CellExtra cellExtra, AnalysisContext analysisContext) {
        log.info("读取到了一条额外信息:{}", JSON.toJSONString(cellExtra));
        switch (cellExtra.getType()) {
            case COMMENT:
                log.info("额外信息是批注,在:{}行,{}列,内容是:{}", cellExtra.getRowIndex(), cellExtra.getColumnIndex(),
                        cellExtra.getText());
                break;
            case HYPERLINK:
                log.info(
                        "额外信息是超链接,而且覆盖了一个区间,第一行索引:{},第一列索引:{},最后一行索引:{},最后一列索引:{},"
                                + "跳转地址是:{}",
                        cellExtra.getFirstRowIndex(), cellExtra.getFirstColumnIndex(), cellExtra.getLastRowIndex(),
                        cellExtra.getLastColumnIndex(), cellExtra.getText());
                break;
            case MERGE:
                log.info(
                        "额外信息是合并单元格,而且覆盖了一个区间,第一行索引:{},第一列索引:{},最后一行索引:{},最后一列索引:{}",
                        cellExtra.getFirstRowIndex(), cellExtra.getFirstColumnIndex(), cellExtra.getLastRowIndex(),
                        cellExtra.getLastColumnIndex());
                break;
            default:
        }
    }

    /**
     * 数据解析完成调用
     * @param analysisContext 获取Excel上下文对象
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 判断是否还有添加数据，保证所有数据全部添加
        if(CollectionUtils.isNotEmpty(dataList)){
            consumer.accept(dataList);
        }
    }
}
